package com.mojiayi.learn.jwt.system.aop;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.google.common.base.Strings;
import com.mojiayi.learn.jwt.system.annotation.VerifyWithJWT;
import com.mojiayi.learn.jwt.system.constant.UserInfoConstant;
import com.mojiayi.learn.jwt.system.exception.NotLoginException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 访问限制接口请求拦截
 *
 * @author mojiayi
 */
@Slf4j
@Aspect
@Component
public class JwtLoginCheckAspect {
    @Autowired
    private HttpServletRequest httpServletRequest;

    @Pointcut("execution(public * com.mojiayi.learn.jwt.controller.*.*(..))")
    public void requestPoint() {

    }

    @Around("requestPoint() && @annotation(verifyWithJWT)")
    public Object rateLimitCheck(ProceedingJoinPoint joinPoint, VerifyWithJWT verifyWithJWT) throws Throwable {
        if (verifyWithJWT.required()) {
            String token = httpServletRequest.getHeader("token");
            if (Strings.isNullOrEmpty(token)) {
                throw new NotLoginException();
            }
            String userId = null;
            try {
                userId = JWT.decode(token).getAudience().get(0);
            } catch (JWTDecodeException e) {
                log.info("failed to decode jwt token,token={}", token);
                throw new NotLoginException();
            }
            // TODO 这里只是简单地用固定的用户信息进行合法性校验，实际项目中不能如此
            if (!UserInfoConstant.TEST_USER_ID.equals(userId)) {
                throw new NotLoginException();
            }
            try {
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(UserInfoConstant.TEST_USER_PWD)).build();
                jwtVerifier.verify(token);
            } catch (JWTVerificationException e) {
                log.info("failed to verify jwt token,token={}", token);
                throw new NotLoginException();
            }
        }
        return joinPoint.proceed();
    }
}
